package com.stud.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.stud.common.enums.FileBusinessType;
import com.stud.common.exception.ServiceException;
import com.stud.common.jdbc.MyJdbcTemplate;
import com.stud.common.mybatis.BaseServiceImpl;
import com.stud.common.utils.StringUtils;
import com.stud.common.utils.file.FileUtils;
import com.stud.common.utils.oss.OssUtil;
import com.stud.system.domain.FileLink;
import com.stud.system.mapper.FileLinkMapper;
import com.stud.system.service.FileLinkService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;


/**
 * 系统文件关联Service业务层处理
 *
 * @author Stud
 * @date 2022-10-08
 */
@Service
public class FileLinkServiceImpl extends BaseServiceImpl<FileLinkMapper, FileLink> implements FileLinkService {

    private final Integer IMAGE_SIZE = 2097152;
    private final Integer VIDEO_SIZE = 20971520;
    @Autowired
    private MyJdbcTemplate jdbcTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public FileLink link(MultipartFile file, FileBusinessType businessType, Long businessId) {
        //如果是单文件,则显出之前已绑定的文件关系
        if (!businessType.isMulti()) {
            LambdaQueryWrapper<FileLink> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(FileLink::getBusinessType, businessType.getCode());
            queryWrapper.eq(FileLink::getBusinessId, businessId);
            this.remove(queryWrapper);
        }
        String fileName = file.getOriginalFilename();

        int pointIndex = fileName.lastIndexOf(".");
        String fileAss = fileName.substring(pointIndex);
        String fileKey = OssUtil.uploadObject(file, businessType);

        if (StringUtils.isBlank(fileKey)) {
            throw new ServiceException("上传失败");
        }

        FileLink fileLink = new FileLink();
        fileLink.setFileName(fileName);
        fileLink.setFileAss(fileAss);
        fileLink.setFileType(FileUtils.getFileTypeByAss(fileAss));
        fileLink.setFileSize(file.getSize());
        fileLink.setFileKey(fileKey);
        fileLink.setBusinessType(businessType.getCode());
        fileLink.setBusinessId(businessId);
        boolean result = this.save(fileLink);

        if (!result) {
            throw new ServiceException("文件关联失败");
        }

        return fileLink;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<FileLink> link(MultipartFile[] files, FileBusinessType businessType, Long businessId) {
        //如果是单文件,则显出之前已绑定的文件关系
        if (!businessType.isMulti()) {
            throw new ServiceException("当前业务不支持多文件上传");
        }
        List<FileLink> fileLinks = Lists.newCopyOnWriteArrayList();
        for (MultipartFile file : files) {
            String fileName = file.getOriginalFilename();

            int pointIndex = fileName.lastIndexOf(".");
            String fileAss = fileName.substring(pointIndex);
            String fileKey = OssUtil.uploadObject(file, businessType);

            if (StringUtils.isBlank(fileKey)) {
                throw new ServiceException("上传失败");
            }
            FileLink fileLink = new FileLink();
            fileLink.setFileName(fileName);
            fileLink.setFileAss(fileAss);
            fileLink.setFileType(FileUtils.getFileTypeByAss(fileAss));
            fileLink.setFileSize(file.getSize());
            fileLink.setFileKey(fileKey);
            fileLink.setBusinessType(businessType.getCode());
            fileLink.setBusinessId(businessId);
            boolean result = this.save(fileLink);
            if (!result) {
                throw new ServiceException("文件关联失败");
            }
            fileLinks.add(fileLink);
        }
        return fileLinks;
    }


    @Override
    public Map<Long, List<FileLink>> fileLinkMap(FileBusinessType businessType, List<Long> businessIds) {
        if (CollectionUtils.isEmpty(businessIds)) {
            return Maps.newHashMap();
        }
        LambdaQueryWrapper<FileLink> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(FileLink::getBusinessType, businessType);
        queryWrapper.in(FileLink::getBusinessId, businessIds);
        List<FileLink> list = this.list(queryWrapper);

        Map<Long, List<FileLink>> fileLinkMap = Maps.newHashMap();

        list.forEach(fileLink -> {
            List<FileLink> tempList;
            if (fileLinkMap.containsKey(fileLink.getBusinessId())) {
                tempList = fileLinkMap.get(fileLink.getBusinessId());
            } else {
                tempList = Lists.newArrayList();
                fileLinkMap.put(fileLink.getBusinessId(), tempList);
            }
            tempList.add(fileLink);
        });
        return fileLinkMap;
    }

    @Override
    public Map<Long, List<Long>> fileLinkIdMap(FileBusinessType businessType, List<Long> businessIds) {
        if (CollectionUtils.isEmpty(businessIds)) {
            return Maps.newHashMap();
        }
        LambdaQueryWrapper<FileLink> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(FileLink::getId, FileLink::getBusinessId);
        queryWrapper.eq(FileLink::getBusinessType, businessType);
        queryWrapper.in(FileLink::getBusinessId, businessIds);
        List<FileLink> list = this.list(queryWrapper);

        Map<Long, List<Long>> fileLinkMap = Maps.newHashMap();

        list.forEach(fileLink -> {
            List<Long> tempList;
            if (fileLinkMap.containsKey(fileLink.getBusinessId())) {
                tempList = fileLinkMap.get(fileLink.getBusinessId());
            } else {
                tempList = Lists.newArrayList();
                fileLinkMap.put(fileLink.getBusinessId(), tempList);
            }
            tempList.add(fileLink.getId());
        });
        return fileLinkMap;
    }

    @Override
    public String upload(MultipartFile file, FileBusinessType businessType, Long businessId) {
        FileLink link = this.link(file, businessType, businessId);
        return link.getFileKey();
    }


}
